home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue32 / bmpanim / BMPANIM.ZIP / BmpAnim.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-08-26  |  12.9 KB  |  508 lines

  1. {
  2.   A bitmap animator: animates a bitmap consisting of multiple likesized bitmaps
  3.   like the explorer logo in Internet Explorer / Mail.
  4.  
  5.   Copyright ⌐ by Peter Th÷rnqvist May 1997; all rights reserved.
  6.   Contact me at NMA96PTH@LUSTUDAT.STUDENT.LU.SE
  7.   You are permitted to use this component free of charge,
  8.   but this is NOT freeware: I retain all rights to it
  9.  
  10.  
  11.   Properties:
  12.     AutoSize : sizes the window to the frame size
  13.     Color : the color to use as transparentcolor
  14.     Direction: specifies which direction the frames are animated.
  15.                Note that changing direction will reset the animation
  16.                to the starting / ending frame.
  17.     Enabled : run / stop animation
  18.     Image : the bitmap to get the frames from
  19.     NumFrames : number of frames in Image
  20.     Orientation : frames are placed left-to-right or top-to-bottom in Image
  21.     Position : what frame to display when stopped (disabled)
  22.     Speed : frames / sec 
  23.     Min : first frame to display
  24.     Max : last frame to display
  25.     Transparent : true if you want Color replaced by transparency
  26.  
  27.   Bugs:
  28.   1 AutoSize doesn't get saved when exiting.
  29.   2 Displaying some bitmaps looks OK when designing but turns black
  30.     when running (explorer strip notably). Don't know why. Seems
  31.     to be more common with vertical bitmaps (???) with black background
  32.   3 Sometimes when manipulating the bitmap at design time, it turns black (like 2 above).
  33.     Saving and reloading the app. seems to solve this.
  34.     Also, displays correctly when run.
  35.  
  36.  
  37.   Limitations:
  38.   1 Uses a timer (oouuh, that's AWFUL!!!).
  39.   2 Flickers a bit sometimes. Placing the control on a panel with the same
  40.     general color, reduces the visibility of this.
  41.   3 Delphi 2.0X (3.0X too maybe?) only.
  42.  
  43.   Installing:
  44.   1 You need BmpAnim.pas and BmpAnim.dcr to install.
  45.   2 Go about it in the normal fashion ( some help, huh? )
  46.   3 Make some movies!
  47. }
  48.  
  49. unit BmpAnim;
  50. interface
  51. uses
  52.   SysUtils, Windows, Messages, Classes, Graphics, Controls,  CommCtrl,
  53.   ExtCtrls;
  54.  
  55. type
  56.   TOrientation=(toHorizontal,toVertical);
  57.   TDirection=(tdForward,tdBack,tdFwdBack,tdBackFwd);
  58.   TCustomBmpAnimator = class(TGraphicControl)
  59.   private
  60.     { Private declarations }
  61.     FImageList:TImageList;
  62.     FTimer:TTimer;
  63.     FIndex:integer;
  64.     FImage:TBitmap;
  65.     FEnabled:boolean;
  66.     FWidth,FHeight:integer;
  67.     FNumGlyphs:integer;
  68.     FOrientation:TOrientation;
  69.     FSpeed:integer;
  70.     FTransparent:boolean;
  71.     FAutoSize:boolean;
  72.     FStart,FStop:integer;
  73.     FPosition:integer;
  74.     FColor:TColor;
  75.     FDirection:TDirection;
  76.     FGoingUp:boolean;
  77.     FCenter:boolean;
  78.     procedure SetCenter(Value:boolean);
  79.     procedure SetDirection(Value:TDirection);
  80.     procedure SetColor(Value:TColor);
  81.     procedure SetPosition(Value:integer);
  82.     procedure SetStart(Value:integer);
  83.     procedure SetStop(Value:integer);
  84.     procedure SetAutoSize(Value:boolean);
  85.     procedure SetTransparent(Value:boolean);
  86.     procedure SetImage(Value:TBitmap);
  87.     procedure SetEnabled(Value:boolean);
  88.     procedure SetNumGlyphs(Value:integer);
  89.     procedure SetOrientation(Value:Torientation);
  90.     procedure SetSpeed(Value:integer);
  91.     procedure TimerEvent(Sender:TObject);
  92.     procedure UpdateImages;
  93.   protected
  94.     { Protected declarations }
  95.     procedure Paint; override;
  96.     property  AutoSize:boolean read FAutoSize write SetAutoSize default False;
  97.     property  Centered:boolean read FCenter write SetCenter;
  98.     property  Color:TColor read FColor write SetColor default clBtnFace;
  99.     property  Direction: TDirection read FDirection write SetDirection;
  100.     property  Enabled:boolean read FEnabled write SetEnabled default False;
  101.     property  Image:TBitmap read FImage write SetImage;
  102.     property  NumFrames:integer read FNumGlyphs write SetNumGlyphs default 0;
  103.     property  Orientation:TOrientation read FOrientation write SetOrientation default toHorizontal;
  104.     property  Position:integer read FPosition write SetPosition default 0;
  105.     property  Speed:integer read FSpeed write SetSpeed default 100;
  106.     property  Min:integer read FStart write SetStart default 0;
  107.     property  Max:integer read FStop write SetStop default 0;
  108.     property  Transparent:boolean read FTransparent write SetTransparent default False;
  109.   public
  110.     { Public declarations }
  111.     constructor Create(AOwner:TComponent);override;
  112.     destructor Destroy; override;
  113.   published
  114.     { Published declarations }
  115.   end;
  116.  
  117.   TBmpAnimator=class(TCustomBmpAnimator)
  118.   private
  119.   protected
  120.   public
  121.   published
  122.     property Align;
  123.     property AutoSize;
  124.     property Centered;
  125.     property Color;
  126.     property Direction;
  127.     property Enabled;
  128.     property Height;
  129.     property Image;
  130.     property Left;
  131.     property Name;
  132.     property NumFrames;
  133.     property Orientation;
  134.     property Position;
  135.     property Speed;
  136.     property Min;
  137.     property Max;
  138.     property Tag;
  139.     property Top;
  140.     property Transparent;
  141.     property Width;
  142.     property OnClick;
  143.     property OnMouseDown;
  144.     property OnMouseMove;
  145.     property OnMouseUp;
  146.     property OnDragDrop;
  147.     property OnEndDrag;
  148.     property OnStartDrag;
  149.     property OnDragOver;
  150.   end;
  151.  
  152. procedure Register;
  153.  
  154. implementation
  155.  
  156. constructor TCustomBmpAnimator.Create(AOwner:TComponent);
  157. begin
  158.   inherited Create(AOwner);
  159.   FImage := TBitmap.Create;
  160.   FWidth := 60;
  161.   FHeight := 60;
  162.   Width := FWidth;
  163.   Height := FHeight;
  164.   FTransparent := False;
  165.   FAutoSize := False;
  166.   FSpeed := 15;
  167.   FNumGlyphs := 0;
  168.   FIndex := 0;
  169.   FStart := 0;
  170.   FStop := 0;
  171.   FPosition := 0;
  172.   FEnabled := False;
  173.   FColor := clBtnFace;
  174.   FOrientation := toHorizontal;
  175.   FImageList := TImageList.CreateSize(FWidth,FHeight);
  176.   FTimer := TTimer.Create(nil);
  177.   FTimer.OnTimer := TimerEvent;
  178.   FTimer.Enabled := FEnabled;
  179.   FTimer.Interval := 100;
  180.   FDirection := tdForward;
  181.   FGoingUp := True;
  182. end;
  183.  
  184. destructor TCustomBmpAnimator.Destroy;
  185. begin
  186.   FImage.Free;
  187.   FImageList.Free;
  188.   FTimer.Enabled := False;
  189.   FTimer.Free;
  190.   inherited Destroy;
  191. end;
  192.  
  193. procedure TCustomBmpAnimator.TimerEvent(Sender:TObject);
  194. var dX,dY:integer;
  195. begin
  196.   if not FEnabled then FIndex := FPosition else
  197.   case FDirection of
  198.     tdForward:
  199.     begin
  200.       Inc(FIndex);
  201.       if (FIndex > FNumGlyphs) or (FIndex > FStop) then
  202.         FIndex := FStart;
  203.     end;
  204.     tdBack:
  205.     begin
  206.       Dec(FIndex);
  207.       if (FIndex < 0) or (FIndex < FStart) then
  208.         FIndex := FStop;
  209.     end;
  210.  
  211.     tdFwdBack,tdBackFwd:
  212.     begin
  213.       if FGoingUp then
  214.       begin
  215.         if (FIndex >= FStop) then
  216.         begin
  217.           FGoingUp := False;
  218.           Dec(FIndex);
  219.         end
  220.         else
  221.           Inc(FIndex);
  222.       end
  223.       else
  224.       begin
  225.         if (FIndex <= FStart) then
  226.         begin
  227.           FGoingUp := True;
  228.           Inc(FIndex);
  229.         end
  230.         else
  231.           Dec(Findex);
  232.       end;
  233.     end;
  234.   end;
  235.  
  236.   if FCenter then
  237.   begin
  238.     dX := (Width - FImageList.Width) div 2;
  239.     dY := (Height - FImageList.Height) div 2;
  240.   end
  241.   else
  242.   begin
  243.     dX := 0;
  244.     dY := 0;
  245.   end;
  246.  
  247.   if FTransparent then
  248.     ImageList_DrawEx(FImageList.Handle, FIndex, Canvas.Handle, dX,dY,0,0,
  249.       clNone, clNone, ILD_Transparent)
  250.   else
  251.   begin
  252.     Canvas.FillRect(ClientRect);
  253.     ImageList_DrawEx(FImageList.Handle, FIndex, Canvas.Handle, dX,dY,0,0,
  254.       ColorToRGB(FColor), FColor, ILD_Normal);
  255.   end;
  256. end;
  257.  
  258.  
  259. procedure TCustomBmpAnimator.UpdateImages;
  260. var i:integer;Bmp:TBitmap;Dest,Source:TRect;
  261. begin
  262.   Canvas.Brush.Color := FColor;
  263.   FImageList.Clear;
  264.  
  265.   if FImage.Empty then Exit;
  266.   if FNumGlyphs = 0 then SetNumGlyphs(1);
  267.   if FOrientation = toHorizontal then
  268.   begin
  269.     FWidth := FImage.Width div FNumGlyphs;
  270.     FHeight := FImage.Height;
  271.   end
  272.   else
  273.   begin
  274.     FWidth := FImage.Width;
  275.     FHeight := FImage.Height div FNumGlyphs;
  276.   end;
  277.  
  278.  
  279.   if (FWidth <> FImageList.Width) or (FHeight <> FImageList.Height) then
  280.   begin
  281.     FImageList.Width := FWidth;
  282.     FImageList.Height := FHeight;
  283.   end;
  284.  
  285.  
  286.   Bmp := TBitmap.Create;
  287.  try
  288.   Bmp.Width := FWidth;
  289.   Bmp.Height := FHeight;
  290.   Dest := Rect(0,0,FWidth,FHeight);
  291.   { create the imagelist }
  292.   for i := 0 to FNumGlyphs - 1 do
  293.   begin
  294.     if FOrientation = toHorizontal then
  295.       Source := Rect(i * FWidth,0,i * FWidth + FWidth,FHeight)
  296.     else
  297.       Source := Rect(0,i * FHeight,FWidth,i * FHeight + FHeight);
  298.     Bmp.Canvas.CopyRect(Bmp.Canvas.ClipRect,FImage.Canvas,Source);
  299.     FImageList.AddMasked(Bmp,Bmp.TransparentColor)
  300.   end;
  301.   if FAutoSize and (Align = alNone) then
  302.     SetBounds(Left,Top,FWidth,FHeight);
  303.  finally
  304.   Bmp.Free;
  305.  end;
  306.   FImage.Dormant;
  307.   Repaint;
  308. end;
  309.  
  310. procedure TCustomBmpAnimator.SetStart(Value:integer);
  311. begin
  312.   if FStart <> Value then
  313.   begin
  314.     FStart := Value;
  315.     if FStart > FStop then FStart := FStop;
  316.     if FStart >= FNumGlyphs then FStart := FNumGlyphs-1;
  317.     if FStart < 0 then FStart := 0;
  318.   end;
  319. end;
  320.  
  321. procedure TCustomBmpAnimator.SetStop(Value:integer);
  322. begin
  323.   if FStop <> Value then
  324.   begin
  325.     FStop := Value;
  326.     if FStop < FStart then FStop := FStart;
  327.     if FStop > FNumGlyphs then FStop := FNumGlyphs-1;
  328.     if FStop < 0 then FStop := 0;
  329.   end;
  330. end;
  331.  
  332.  
  333. procedure TCustomBmpAnimator.SetAutoSize(Value:boolean);
  334. begin
  335.   if FAutoSize <> Value then
  336.   begin
  337.     FAutoSize := Value;
  338.     UpdateImages;
  339.   end;
  340. end;
  341.  
  342. procedure TCustomBmpAnimator.SetTransparent(Value:boolean);
  343. begin
  344.   if FTransparent <> Value then
  345.   begin
  346.     FTransparent := Value;
  347.     if FTransparent then
  348.       FImageList.DrawingStyle := dsTransparent
  349.     else
  350.       FImageList.DrawingStyle := dsNormal;
  351.     UpdateImages;
  352.   end;
  353. end;
  354.  
  355. procedure TCustomBmpAnimator.SetImage(Value:TBitmap);
  356. begin
  357.   if FImage <> Value then
  358.   with FImage do
  359.   begin
  360.    Assign(Value);
  361.    if not FImage.Empty then
  362.    begin
  363.      if Width > Height then SetOrientation(toHorizontal)
  364.      else SetOrientation(toVertical);
  365.      if Width mod Height = 0 then
  366.        SetNumGlyphs(Width div Height)
  367.      else if Height mod Width = 0 then
  368.        SetNumGlyphs(Height div Width)
  369.      else if FNumGlyphs = 0 then
  370.        SetNumGlyphs(1);
  371.      SetStart(FStart);
  372.      SetStop(FNumGlyphs-1);
  373.    end;
  374.    UpdateImages;
  375.   end;
  376. end;
  377.  
  378. procedure TCustomBmpAnimator.SetEnabled(Value:boolean);
  379. begin
  380.   if not Assigned(FimageList) then
  381.     Value := False;
  382.   if FEnabled <> Value then
  383.   begin
  384.     FEnabled := Value;
  385.     FTimer.Enabled := FEnabled;
  386.     FIndex := FStart;
  387.   end;
  388.   Repaint;
  389. end;
  390.  
  391.  
  392. procedure TCustomBmpAnimator.SetNumGlyphs(Value:integer);
  393. begin
  394.   if FNumGlyphs <> Value then
  395.   begin
  396.     FNumGlyphs := Value;
  397.     SetStop(FNumGlyphs-1);
  398.     UpdateImages;
  399.   end;
  400. end;
  401.  
  402. procedure TCustomBmpAnimator.SetOrientation(Value:Torientation);
  403. begin
  404.   if FOrientation <> Value then
  405.   begin
  406.     FOrientation := Value;
  407.     UpdateImages;
  408.   end;
  409. end;
  410.  
  411. procedure TCustomBmpAnimator.SetSpeed(Value:integer);
  412. begin
  413.   if FSpeed <> Value then
  414.   begin
  415.     FSpeed := Value;
  416.     FTimer.Interval := 1000 div FSpeed;
  417.   end;
  418. end;
  419.  
  420. procedure TCustomBmpAnimator.SetCenter(Value:boolean);
  421. begin
  422.   if FCenter <> value then
  423.   begin
  424.     FCenter := Value;
  425.     Invalidate;
  426.   end;
  427. end;
  428.  
  429. procedure TCustomBmpAnimator.SetDirection(Value:TDirection);
  430. begin
  431.   if FDirection <> Value then
  432.   begin
  433.     FDirection := Value;
  434.     case FDirection of
  435.       tdForward,tdFwdBack: begin
  436.         FGoingUp := True;
  437.         FIndex := FStart;
  438.       end;
  439.       tdBack,tdBackFwd:
  440.       begin
  441.         FGoingUp := False;
  442.         FIndex := FStop;
  443.       end;
  444.     end;
  445.   end;
  446. end;
  447.  
  448. procedure TCustomBmpAnimator.SetColor(Value:TColor);
  449. begin
  450.   if FColor <> Value then
  451.   begin
  452.     FColor := Value;
  453.     UpdateImages;
  454.   end;
  455. end;
  456.  
  457. procedure TCustomBmpAnimator.SetPosition(Value:integer);
  458. begin
  459.   FPosition := Value;
  460.   if FPosition > FNumGlyphs-1 then
  461.     FPosition := FNumGlyphs-1;
  462.   Invalidate;
  463. end;
  464.  
  465. procedure TCustomBmpAnimator.Paint;
  466. var dX,dY:integer;
  467. begin
  468.     if {(FImage.Empty) or }(csDesigning in ComponentState) then
  469.     begin
  470.       Canvas.Brush.Color := clBlack;
  471. //      Canvas.Pen.Color := FColor;
  472.       Canvas.FrameRect(GetClientRect);
  473.       Canvas.Brush.Color := FColor;
  474.       if not FTransparent then
  475.         Canvas.FillRect(GetClientRect);
  476.     end;
  477.     if not (FImage.Empty) then
  478.     begin
  479.       if FCenter then
  480.       begin
  481.         dX := (Width - FImageList.Width) div 2;
  482.         dY := (Height - FImageList.Height) div 2;
  483.       end
  484.       else
  485.       begin
  486.         dX := 0;
  487.         dY := 0;
  488.       end;
  489.     
  490.       if FTransparent then
  491.         ImageList_DrawEx(FImageList.Handle, FPosition, Canvas.Handle, dX,dY,0,0,
  492.           clNone, FColor, ILD_Transparent)
  493.       else
  494.       begin
  495.         Canvas.FillRect(ClientRect);
  496.         ImageList_DrawEx(FImageList.Handle, FPosition, Canvas.Handle, dX,dY,0,0,
  497.           ColorToRGB(FColor), FColor, ILD_Normal);
  498.       end;
  499.     end;
  500. end;
  501.  
  502. procedure Register;
  503. begin
  504.   RegisterComponents('Samples', [TBmpAnimator]);
  505. end;
  506.  
  507. end.
  508.